from music21 import converter, note, chord
from data_output import write_to_py_file  # 确保引入要调用的函数

def convert_to_sharp_pitch(pitch):
    """将降号音符转换为升号音符"""
    if pitch == 'A-':
        return 'G#'
    if pitch == 'B-':
        return 'A#'
    elif pitch == 'C-':
        return 'B'  # C- 实际是 B
    elif pitch == 'D-':
        return 'C#'
    elif pitch == 'E-':
        return 'D#'
    elif pitch == 'F-':
        return 'E'  # F- 实际是 E
    elif pitch == 'G-':
        return 'F#'
    return pitch  # 如果没有降号，返回原音名

def extract_notes_from_musicxml(musicxml_file):
    """从 MusicXML 文件中提取音符及和弦信息并以二维数组格式返回"""
    output_data = []  # 存储输出数据的列表

    # 尝试解析 MusicXML 文件
    try:
        score = converter.parse(musicxml_file)
        print(f"[INFO] 成功加载 MusicXML 文件: {musicxml_file}")
    except Exception as e:
        print(f"[ERROR] 无法加载 MusicXML 文件: {e}")
        return []

    # 获取乐谱中的所有部分
    parts = score.getElementsByClass('Part')
    if not parts:
        print("[WARNING] 在乐谱中未找到部分。")
        return []

    for part in parts:
        measures = part.getElementsByClass('Measure')  # 从 Part 中获取小节
        if not measures:
            print("[WARNING] 在该部分中未找到小节。")
            return []

        for measure in measures:
            measure_start_time = measure.offset * 1000  # 小节的开始时间

            for element in measure.notes:
                if isinstance(element, note.Note):
                    # 获取音符信息
                    pname = element.name
                    octave = element.octave
                    name = f"{convert_to_sharp_pitch(pname)}{octave}"  # 转换音名并添加八度
                elif isinstance(element, chord.Chord):
                    # 对和弦进行处理
                    name = '+'.join(f"{convert_to_sharp_pitch(n.name)}{n.octave}" for n in element.notes)

                # 获取音符的持续时间并计算结束时间
                duration_ms = int(element.quarterLength * 1000)  # 持续时间（毫秒）
                end_time = measure_start_time + duration_ms  # 计算终止时间

                # 将数据添加到输出列表中
                output_data.append([measure_start_time, end_time, name])

    return output_data  # 返回二维数组

if __name__ == "__main__":
    musicxml_file_path = './test_data/diyin.musicxml'  # 确保路径正确，替换为你的 MusicXML 文件路径
    output_py_file_name = 'results_output.py'  # 输出文件名
    print(f"[INFO] 开始处理文件: {musicxml_file_path}")

    extracted_data = extract_notes_from_musicxml(musicxml_file_path)
    if extracted_data:
        # 注意调用 data_output.py 中的写入函数来输出数据
        write_to_py_file(output_py_name=output_py_file_name, output_data=extracted_data,write_mode='string')